package com.fancy.application.common.utils;

import cn.hutool.system.OsInfo;
import lombok.extern.log4j.Log4j2;

import java.io.*;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@Log4j2

public class FileUtils {

  /**

   * 复制文件到目标目录

   * @param resourcePath resource的文件夹路径

   * @param tmpDir 临时目录

   * @param fileType 文件类型

   */

public static void copyJavaResourceDir2TmpDir(String resourcePath, String tmpDir, FileType fileType) {

    Map<String, Object> fileMap = new HashMap<>();

    if (resourcePath.endsWith("/")) {
      resourcePath = resourcePath.substring(0, resourcePath.lastIndexOf("/"));

    }

    try {
      Enumeration resources = null;
      try {

        resources = Thread.currentThread().getContextClassLoader().getResources(resourcePath);

      } catch (Exception ex) {

        ex.printStackTrace();

      }

      if (resources == null || !resources.hasMoreElements()) {

        resources = FileUtils.class.getClassLoader().getResources(resourcePath);

      }

      while (resources.hasMoreElements()) {

        URL resource = (URL) resources.nextElement();

        if (resource.getProtocol().equals("file")) { // resource是文件

          continue;

        }

        String[] split = resource.toString().split(":");

        String filepath = split[2];
          OsInfo oi = new OsInfo();
        if (oi.isWindows()) {

          filepath = filepath + ":" + split[3];

        }

        String[] split2 = filepath.split("!");

        String zipFileName = split2[0];

        ZipFile zipFile = new ZipFile(zipFileName);

        Enumeration entries = zipFile.entries();

        while (entries.hasMoreElements()) {

          ZipEntry entry = (ZipEntry) entries.nextElement();

          String entryName = entry.getName();

          if (entry.isDirectory()) {

            continue;

          }

          if (entryName.contains(resourcePath) && entryName.endsWith(fileType.toString().toLowerCase())) {

            String dir = entryName.substring(0, entryName.lastIndexOf("/"));

            if (!dir.endsWith(resourcePath)) { // 目标路径含有子目录

              dir = dir.substring(dir.indexOf(resourcePath) + resourcePath.length() + 1);

              if (dir.contains("/")) { // 多级子目录

                String[] subDir = dir.split("/");

                Map<String, Object> map = fileMap;

                for (String d : subDir) {

                  map = makeMapDir(map, d);

                }

                map.putAll(readOneFromJar(zipFile.getInputStream(entry), entryName));

              } else { //一级子目录

                if (fileMap.get(dir) == null) {

                  fileMap.put(dir, new HashMap<String, Object>());

                }

                ((Map<String, Object>) fileMap.get(dir))

                    .putAll(readOneFromJar(zipFile.getInputStream(entry), entryName));

              }

            } else { // 目标路径不含子目录

              fileMap.putAll(readOneFromJar(zipFile.getInputStream(entry), entryName));

            }

          }

        }

      }

    } catch (Exception e) {

      log.error("读取resource文件异常：", e);

    } finally {

      try {

        // 写到目标缓存路径

        createFile(fileMap, tmpDir);

      } catch (Exception e) {

        log.error("创建临时文件异常：", e);

      }

    }

  }

  private static void createFile(Map<String, Object> fileMap, String targetDir) {

    fileMap.forEach((key, value) -> {

      if (value instanceof Map) {

        createFile((Map<String, Object>) value, targetDir + File.separator + key);

      } else {

        createNewFile(targetDir + File.separator + key, value.toString());

      }

    });

  }

  public static void createNewFile(String filePath, String value) {

    try {

      File file = new File(filePath);

      if (!file.exists()) {

        File parentDir = file.getParentFile();

        if (!parentDir.exists()) {

          parentDir.mkdirs();

        }

        file.createNewFile();

      }

      PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8")));

      out.write(value);

      out.flush();

      out.close();

    } catch (Exception e) {

      log.error("创建文件异常：", e);

    }

  }

  private static Map<String, Object> makeMapDir(Map<String, Object> fileMap, String d) {

    if (fileMap.get(d) == null) {

      fileMap.put(d, new HashMap<String, Object>());

    }

    return (Map<String, Object>) fileMap.get(d);

  }

  public static Map<String, String> readOneFromJar(InputStream inputStream, String entryName) {

    Map<String, String> fileMap = new HashMap<>();

    try (Reader reader = new InputStreamReader(inputStream, "utf-8")) {

      StringBuilder builder = new StringBuilder();

      int ch = 0;

      while ((ch = reader.read()) != -1) {

        builder.append((char) ch);

      }

      String filename = entryName.substring(entryName.lastIndexOf("/") + 1);

      fileMap.put(filename, builder.toString());

    } catch (Exception ex) {

      log.error("读取文件异常：", ex);

    }

    return fileMap;

  }

  public enum FileType {
    JSON
  }

}
